home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / STK100.ZIP / PLAYDWM.C < prev    next >
C/C++ Source or Header  |  1995-02-21  |  12KB  |  482 lines

  1. /******************************************************************************
  2. File:          playdwm.c
  3. Tab stops: every 2 collumns
  4. Project:     DWM Player
  5. Copyright: 1994 DiamondWare, Ltd.  All rights reserved.*
  6. Written:     Keith Weiner & Erik Lorenzen
  7. Purpose:     Contains simple example code to show how to load/play a .DWM file
  8. History:     KW 10/21/94 Started
  9.                      EL 02/21/95 Finalized
  10.  
  11. Notes
  12. -----
  13.  
  14. The bulk of this file is error checking logic.
  15.  
  16. However, this code isn't really robust when it comes to standard error checking
  17. and particularly recovery, software engineering technique, etc.  A buffer
  18. is statically allocated.    A better technique would be to use fstat() or stat()
  19. to determine the file's size then malloc(size).  The STK will handle songs
  20. larger than 64K (but not digitized sounds).  Obviously, you'd need to fread()
  21. such a file in chunks, or write some sort of hfread() (huge fread).  Also,
  22. exitting and cleanup is not handled robustly in this code.    The code below can
  23. only be validated by extremely careful scrutiny to make sure each case is
  24. handled properly.  A better method would the use of C's atexit function.
  25.  
  26. But all such code would make this example file less clear; its purpose was
  27. to illustrate how to call the STK, not how to write QA-proof software.
  28.  
  29.  
  30. *Permission is expressely granted to use DisplayError or any derivitive made
  31.  from it to registered users of the STK.
  32. ******************************************************************************/
  33.  
  34.  
  35.  
  36. #include <stdio.h>
  37. #include <stdlib.h>
  38. #include <conio.h>
  39.  
  40. #include "dws.h"
  41. #include "dwt.h"
  42.  
  43.  
  44. #define BUFFSIZE 65535        //If the linker outputs the error
  45.                                                     //"stack plus data exceed 64K"
  46.                                                     //try reducing BUFFSIZE to about 32K,
  47.                                                     //or compile for large model.
  48. byte song[BUFFSIZE];
  49.  
  50.  
  51.  
  52. static void DisplayError(word errornum)
  53. {
  54.     switch (errornum)
  55.     {
  56.         case dws_EZERO:
  57.         {
  58.             /*
  59.              . This should not have happened, considering how we got here!
  60.             */
  61.             printf("I'm confused!  Where am I?  HOW DID I GET HERE????\n");
  62.             printf("The ERROR number is: %d\n",errornum);
  63.  
  64.             break;
  65.         }
  66.         case dws_NOTINITTED:
  67.         {
  68.             /*
  69.              . If we get here, it means you haven't called dws_Init().
  70.              . The STK needs to initialize itself and the hardware before
  71.              . it can do anything.
  72.             */
  73.             printf("The STK was not initialized\n");
  74.  
  75.             break;
  76.         }
  77.         case dws_ALREADYINITTED:
  78.         {
  79.             /*
  80.              . If we get here, it means you've called dws_Init() already.  Calling
  81.              . dws_DetectHardWare() at this point would cause zillions of
  82.              . problems if we let the call through.
  83.             */
  84.             printf("The STK was already initialized\n");
  85.  
  86.             break;
  87.         }
  88.         case dws_NOTSUPPORTED:
  89.         {
  90.             /*
  91.              . If we get here, it means that either the user's machine does not
  92.              . support the function you just called, or the STK was told not to
  93.              . support it in dws_Init.
  94.             */
  95.             printf("Function not supported\n");
  96.  
  97.             break;
  98.         }
  99.         case dws_DetectHardware_UNSTABLESYSTEM:
  100.         {
  101.             /*
  102.              . Please report it to DiamondWare if you get here!
  103.              .
  104.              . Ideally, you would disable control-C here, so that the user can't
  105.              . hit control-alt-delete, causing SmartDrive to flush its (possibly
  106.              . currupt) buffers.
  107.             */
  108.             printf("The system is unstable!\n");
  109.             printf("Please power down now!");
  110.  
  111.             #define ever ;;
  112.             for (ever);
  113.         }
  114.  
  115.         /*
  116.          . The following three errors are USER/PROGRAMMER errors.  You forgot
  117.          . to fill the cardtyp struct full of -1's (except in those fields
  118.          . you intended to override, or the user (upon the unlikly event that
  119.          . the STK was unable to find a card) gave you a bad overide value.
  120.         */
  121.         case dws_DetectHardware_BADBASEPORT:
  122.         {
  123.             /*
  124.              . You set dov.baseport to a bad value, or
  125.              . didn't fill it with a -1.
  126.             */
  127.             printf("Bad port address\n");
  128.  
  129.             break;
  130.         }
  131.         case dws_DetectHardware_BADDMA:
  132.         {
  133.             /*
  134.              . You set dov.digdma to a bad value, or
  135.              . didn't fill it with a -1.
  136.             */
  137.             printf("Bad DMA channel\n");
  138.  
  139.             break;
  140.         }
  141.         case dws_DetectHardware_BADIRQ:
  142.         {
  143.             /*
  144.              . You set dov.digirq to a bad value, or
  145.              . didn't fill it with a -1.
  146.             */
  147.             printf("Bad IRQ level\n");
  148.  
  149.             break;
  150.         }
  151.         case dws_Kill_CANTUNHOOKISR:
  152.         {
  153.             /*
  154.              . The STK points the interrupt vector for the sound card's IRQ
  155.              . to its own code in dws_Init.
  156.              .
  157.              . dws_Kill was unable to restore the vector to its original
  158.              . value because other code has hooked it after the STK
  159.              . initialized(!)  This is really bad.    Make the user get rid
  160.              . of it and call dws_Kill again.
  161.             */
  162.             printf("Get rid of your TSR, pal!\n");
  163.             printf("(Press any key)\n");
  164.             getch();
  165.  
  166.             break;
  167.         }
  168.         case dws_X_BADINPUT:
  169.         {
  170.             /*
  171.              . The mixer funtions can only accept volumes between 0 & 255,
  172.              . the volume will remain unchanged.
  173.             */
  174.             printf("Bad mixer level\n");
  175.  
  176.             break;
  177.         }
  178.         case dws_D_NOTADWD:
  179.         {
  180.             /* You passed the STK a pointer to something which is not a .DWD file! */
  181.             printf("The file you are attempting to play is not a .DWD\n");
  182.  
  183.             break;
  184.         }
  185.         case dws_D_NOTSUPPORTEDVER:
  186.         {
  187.             /*
  188.              . The STK can't play a .DWD converted using a version of VOC2DWD.EXE
  189.              . newer than itself.  And, although we'll try to maintain backwards
  190.              . compatibility, we may not be able to guarantee that newer versions
  191.              . of the code will be able to play older .DWD files.  In any event,
  192.              . it's a good idea to always convert .VOC files with the utility
  193.              . which comes with the library you're linking into your application.
  194.             */
  195.             printf("Please reconvert this file using the VOC2DWD.EXE which came with this library");
  196.  
  197.             break;
  198.         }
  199.         case dws_D_INTERNALERROR:
  200.         {
  201.             /*
  202.              . This error should never occur and probably will not affect sound
  203.              . play(?).  If it happens please contact DiamondWare.
  204.             */
  205.             printf("An internal error has occured\nPlease contact DiamondWare\n");
  206.  
  207.             break;
  208.         }
  209.         case dws_DPlay_NOSPACEFORSOUND:
  210.         {
  211.             /*
  212.              . This error is more like a warning, though it may happen on a
  213.              . regular basis, depending on how many sounds you told the STK
  214.              . to allow in dws_Init, how you chose to prioritize sounds and
  215.              . how many sounds are currently being played.
  216.             */
  217.             printf("No more room for new digitized sounds right now\n");
  218.  
  219.             break;
  220.         }
  221.         case dws_DSetRate_FREQTOLOW:
  222.         {
  223.             /*
  224.              . The STK will set rate as close as possible to the indicated rate
  225.              . but cannot set a rate that low.
  226.             */
  227.             printf("Playback frequency too low\n");
  228.  
  229.             break;
  230.         }
  231.         case dws_DSetRate_FREQTOHIGH:
  232.         {
  233.             /*
  234.              . The STK will set rate as close as possible to the indicated rate
  235.              . but cannot set a rate that high.
  236.             */
  237.             printf("Playback frequency too high\n");
  238.  
  239.             break;
  240.         }
  241.         case dws_MPlay_NOTADWM:
  242.         {
  243.             /*
  244.              . You passed the STK a pointer to something which is not a .DWM file!
  245.             */
  246.             printf("The file you are attempting to play is not a .DWM\n");
  247.  
  248.             break;
  249.         }
  250.         case dws_MPlay_NOTSUPPORTEDVER:
  251.         {
  252.             /*
  253.              . The STK can't play a .DWM converted using a version of VOC2DWM.EXE
  254.              . newer than itself.  And, although we'll try to maintain backwards
  255.              . compatibility, we may not be able to guarantee that newer versions
  256.              . of the code will be able to play older .DWM files.  In any event,
  257.              . it's a good idea to always convert .MID files with the utility
  258.              . which comes with the library you're linking into your application.
  259.             */
  260.             printf("Please reconvert this file using the MID2DWM.EXE which came with this library");
  261.  
  262.             break;
  263.         }
  264.         case dws_MPlay_INTERNALERROR:
  265.         {
  266.             /*
  267.              . This error should never occur and probably will not affect sound
  268.              . play(?).  If it happens please contact DiamondWare.
  269.             */
  270.             printf("An internal error has occured\nPlease contact DiamondWare\n");
  271.  
  272.             break;
  273.         }
  274.         default:
  275.         {
  276.             /*
  277.              . This should never occur and probably will not affect sound
  278.              . play(?). If it happens please contact DiamondWare.
  279.             */
  280.             printf("I'm confused!  Where am I?  HOW DID I GET HERE????\n");
  281.             printf("The ERROR number is: %d\n",errornum);
  282.         }
  283.     }
  284. }
  285.  
  286.  
  287. void main(int argc, char **argv)
  288. {
  289.     FILE                                *fp;
  290.     dws_DETECTOVERRIDES dov;
  291.     dws_DETECTRESULTS     dres;
  292.     dws_IDEAL                     ideal;
  293.     dws_MPLAY                     mplay;
  294.     int                                 input=0;
  295.     word                                musvol=255;     //Default mxr volume at startup is max
  296.     word                                songstatus;
  297.  
  298.     printf("\nPLAYDWM is Copyright 1994 DiamondWare, Ltd.\nAll rights reserved.\n\n\n");
  299.  
  300.     if (argc < 2)
  301.     {
  302.         printf("Usage PLAYDWM <dwm-file>\n");
  303.         exit(-1);
  304.     }
  305.  
  306.     fp = fopen(argv[1], "rb");
  307.  
  308.     if (fp == NULL)
  309.     {
  310.         printf("Unable to open %s\n", argv[1]);
  311.         exit(-1);
  312.     }
  313.  
  314.     fread(song, (size_t)BUFFSIZE, 1, fp);  //if file's len < BUFFSIZE, this works
  315.  
  316.     fclose(fp);
  317.  
  318.     /*
  319.      . We need to set every field to -1 in dws_DETECTOVERRIDES struct; this
  320.      . tells the STK to autodetect everything.    Any other value
  321.      . overrides the autodetect routine, and will be accepted on
  322.      . faith, though the STK will verify it if possible.
  323.     */
  324.     dov.baseport = (word)-1;
  325.     dov.digdma     = (word)-1;
  326.     dov.digirq     = (word)-1;
  327.  
  328.     if (!dws_DetectHardWare(&dov, &dres))
  329.     {
  330.         DisplayError(dws_ErrNo());
  331.         exit(-1);
  332.     }
  333.  
  334.     if (!(dres.capability & dws_capability_FM))
  335.     {
  336.         printf("FM support not found\n");
  337.         exit(-1);
  338.     }
  339.  
  340.     /*
  341.      . The "ideal" struct tells the STK how you'd like it to initialize the
  342.      . sound hardware.    In all cases, if the hardware won't support your
  343.      . request, the STK will go as close as possible.  For example, not all
  344.      . sound boards will support al sampling rates (some only support 5 or
  345.      . 6 discrete rates).
  346.     */
  347.     ideal.musictyp     = 1;             //for now, it's OPL2 music
  348.     ideal.digtyp         = 0;             //0=No Dig, 8=8bit, 16=16bit
  349.     ideal.digrate      = 0;             //sampling rate, in Hz
  350.     ideal.dignvoices = 0;             //number of voices (up to 16)
  351.     ideal.dignchan     = 0;             //1=mono, 2=stereo
  352.  
  353.     if (!dws_Init(&dres, &ideal))
  354.     {
  355.         DisplayError(dws_ErrNo());
  356.         exit(-1);
  357.     }
  358.  
  359.     /*
  360.      . 72.8Hz is a decent compromise.  It will work in a Windows DOS box
  361.      . without any problems, and yet it allows music to sound pretty good.
  362.      . In my opinion, there's no reason to go lower than 72.8 (unless you
  363.      . don't want the hardware timer reprogrammed)--music sounds kinda chunky
  364.      . at lower rates.    You can go to 145.6 Hz, and get smoother (very
  365.      . subtly) sounding music, at the cost that it will NOT run at the correct
  366.      . (or constant) speed in a Windows DOS box.
  367.     */
  368.     dwt_Init(dwt_72_8HZ);
  369.  
  370.     /*
  371.      . Set Music Volume to about 4/5 th's of max
  372.     */
  373.     musvol = 200;
  374.     if (!dws_XMusic(musvol))
  375.     {
  376.         DisplayError(dws_ErrNo());
  377.     }
  378.  
  379.     mplay.track = song;
  380.     mplay.count = 1;                        //0=infinite loop, 1-N num times to play sound
  381.  
  382.     if (!dws_MPlay(&mplay))
  383.     {
  384.         DisplayError(dws_ErrNo());
  385.         goto KillIt;
  386.     }
  387.  
  388.     /*
  389.      . We're playing.  Let's exit when the song is over, and allow the user
  390.      . to fiddle with the volume level (mixer) in the meantime
  391.     */
  392.  
  393.     if (!dws_MSongStatus(&songstatus))
  394.     {
  395.         DisplayError(dws_ErrNo());
  396.         goto KillIt;
  397.     }
  398.  
  399.     printf("Press + or - to change playback volume \n");
  400.  
  401.     while (songstatus)
  402.     {
  403.         if (kbhit())
  404.         {
  405.             input = getch();
  406.         }
  407.         else
  408.         {
  409.             input = 0;
  410.         }
  411.  
  412.         switch (input)
  413.         {
  414.             case 'q':
  415.             case 'Q':
  416.             case 27:                                //ESC
  417.             {
  418.                 if (!dws_MClear())
  419.                 {
  420.                     DisplayError(dws_ErrNo());
  421.                 }
  422.  
  423.                 break;
  424.             }
  425.             case '+':
  426.             {
  427.                 musvol++;
  428.  
  429.                 printf("Music Volume is %d\n", musvol);
  430.  
  431.                 if (!dws_XMusic(musvol))
  432.                 {
  433.                     DisplayError(dws_ErrNo());
  434.                 }
  435.  
  436.                 break;
  437.             }
  438.             case '-':
  439.             {
  440.                 musvol--;
  441.  
  442.                 printf("Music Volume is %d\n", musvol);
  443.  
  444.                 if (!dws_XMusic(musvol))
  445.                 {
  446.                     DisplayError(dws_ErrNo());
  447.                 }
  448.  
  449.                 break;
  450.             }
  451.         }
  452.  
  453.         if (!dws_MSongStatus(&songstatus))
  454.         {
  455.             DisplayError(dws_ErrNo());
  456.             goto KillIt;
  457.         }
  458.     }
  459.  
  460.     KillIt:
  461.  
  462.     dwt_Kill();
  463.  
  464.     KillIt2:
  465.  
  466.     if (!dws_Kill())
  467.     {
  468.         /*
  469.          . If an error occurs here, it's either dws_Kill_CANTUNHOOKISR
  470.          . or dws_NOTINITTED.  If it's dws_Kill_CANTUNHOOKISR the user
  471.          . must remove his tsr, and dws_Kill must be called again.    If it's
  472.          . dws_NOTINITTED, there's nothing to worry about at this point.
  473.         */
  474.         DisplayError(dws_ErrNo());
  475.  
  476.         if (dws_ErrNo() ==    dws_Kill_CANTUNHOOKISR)
  477.         {
  478.             goto KillIt2;
  479.         }
  480.     }
  481. }
  482.